package com.boboPlanet.user.async;

import com.alibaba.fastjson.JSON;
import com.boboPlanet.comm.constance.BaseDictConfigEnum;
import com.boboPlanet.comm.context.BusinessStartTimeContext;
import com.boboPlanet.comm.context.BusinessThreadContextHolder;
import com.boboPlanet.comm.entity.po.LoginUserInfoPO;
import com.boboPlanet.comm.rabbitmq.PlanetMqProducer;
import com.boboPlanet.comm.rabbitmq.producer.PlanetMqTopic;
import com.boboPlanet.comm.result.ResponseResult;
import com.boboPlanet.comm.utils.AutoGenerateIds;
import com.boboPlanet.user.entity.dto.SysLogDTO;
import com.boboPlanet.user.entity.po.SysMsgPO;
import com.boboPlanet.user.enums.MsgTypeEnum;
import com.boboPlanet.user.mq.PlanetMiddleMqEnum;
import com.boboPlanet.user.enums.RoleEnumDict;
import com.boboPlanet.user.feignApi.SysLogApi;
import com.boboPlanet.user.mapper.UserOperationMapper;
import com.boboPlanet.user.socket.WebSocketServerClient;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @Description: TODO
 * @Author: mis_wu
 * @Date: 2023/2/14
 **/
@Data
@Component
@Slf4j
public class AsyncTask {

    @Resource
    private UserOperationMapper userOperationMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private SysLogApi sysLogApi;

    @Resource(name = "multiTaskThreadHandler")
    private ThreadPoolTaskExecutor multiTaskThreadHandler;

    @Resource
    private WebSocketServerClient webSocketServerClient;

    @Resource
    private PlanetMqTopic topic;

    @Resource
    private PlanetMqProducer planetMqProducer;


    @Async("taskExecutor")
    public void loginTaskExecute(LoginUserInfoPO loginUserInfoPO, String redisToken, BusinessThreadContextHolder capture) throws IOException {

        capture.inject();

        String userPo = JSON.toJSONString(loginUserInfoPO);

        //update 数据库 token、登录有效期
        userOperationMapper.updateLoginToken(loginUserInfoPO,redisToken);

        Map<Object,Object> ojbMap = new HashMap<>();

        //用户信息为空,有效期内首次登录
        ojbMap.put(loginUserInfoPO.getLoginAccount(),userPo);
        stringRedisTemplate.opsForHash().putAll(redisToken ,ojbMap);

        //发送websocket及mq
        SysMsgPO po = new SysMsgPO();
        po.setMessageId(AutoGenerateIds.getGenerateId());
        po.setSysName(BaseDictConfigEnum.bobo_planet.name());
        po.setMsgBusinessId(String.valueOf(loginUserInfoPO.getUserId()));
        po.setMsgTitle("星球用户登录");
        String loginMsg = "账户:"+loginUserInfoPO.getLoginAccount()+" 登录成功!!!";
        po.setMsgContent(loginMsg);
        po.setMsgSenderId(-1L);
        po.setMsgSender(RoleEnumDict.sys_admin.getRoleName());
        po.setMsgReceiverId(loginUserInfoPO.getUserId());
        po.setMsgReceiver(loginUserInfoPO.getUserName());
        po.setMsgType(MsgTypeEnum.success.name());
        po.setMsgSendTime(BusinessStartTimeContext.getTime());
        po.setPlanetUpdateTime(BusinessStartTimeContext.getTime());
        po.setVersion(0);
        topic.queue(PlanetMiddleMqEnum.USER_LOGIN_MQ.getQueue())
                .exchange(PlanetMiddleMqEnum.USER_LOGIN_MQ.getExchange())
                .routingKey(PlanetMiddleMqEnum.USER_LOGIN_MQ.getRoutingKey())
                .sendMsg(po);

        String msg = JSON.toJSONString(po);
        webSocketServerClient.sendMsg(msg);

    }

    @Async("taskExecutor")
    public void logoutTask(Long accountId,String account,String token){

        //清空账户信息
        userOperationMapper.clearUserLoginState(accountId);

        stringRedisTemplate.opsForHash().delete(token,account);

    }

    @Async("taskExecutor")
    public void tranceLog(SysLogDTO dto){
        if (ObjectUtils.isEmpty(dto)){
            return;
        }
        ResponseResult<Boolean> result = sysLogApi.addSysLog(dto);
        if (result == null || !result.getSuccess() || !result.getData()){
            log.error("log trance record result is: {}",result);
            log.error("log trance fail,log detail is: {}",dto);
        }

    }

    @Async("taskExecutor")
    public void batchTranceLog(Collection<SysLogDTO> dtoList){
        if (dtoList.isEmpty()){
            return;
        }

        for (SysLogDTO dto : dtoList) {
            tranceLog(dto);
        }
    }

}
